package vnc.ui;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;

import jpcap.packet.Packet;
import vnc.JDPacketAnalyzerLoader;
import vnc.VncFrame;
import vnc.analyzer.ARPAnalyzer;
import vnc.analyzer.JDPacketAnalyzer;


public class BoxContainer extends JScrollPane implements Runnable{

	public static boolean stopPoint;
	public static boolean lastPoint;
	public static int boxSize;
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	Thread t;
	JPanel jp;
	
	
	final MovingBox mb;
	
	final List<PacketBox> boxes;
	
	final List<Packet> packets;
	
	List<JDPacketAnalyzer> analyzers;

	public BoxContainer(List<Packet> packets, List<PacketBox> boxes, MovingBox mb){
		this.stopPoint = true;
		t = new Thread(this, "Box Container");
		
		this.mb = mb;
		
		this.packets = packets;
		
		this.boxes = boxes;
		
		analyzers = JDPacketAnalyzerLoader.getAnalyzers();
		
		init();

	}
	
	private ImageIcon getImageIcon(final String path){
		return new ImageIcon(this.getClass().getResource(path));
	}
	
	private ImageIcon scaleImageIcon(ImageIcon icon, final int width, final int height){
		Image img = icon.getImage();
		
		Image newimg = img.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH);
		
		icon = new ImageIcon(newimg);

		return icon;
	}

	public void init(){
		
		jp = new JPanel();
		
		boxSize = 0;
		
		jp.setBackground(Color.WHITE);
		
		jp.setLayout(null);
		
		this.setViewportView(jp);
		
		this.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
		this.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		//this.getVerticalScrollBar().setBlockIncrement(16);
		
	}
public void saveBox(){
		
		Packet packet;
		for(int j=0;j<boxes.size();j++)
		{
		packet = this.boxes.get(j).packet;
		
		for(JDPacketAnalyzer analyzer:analyzers){
			
			if(analyzer.isAnalyzable(packet))
			{
				analyzer.analyze(packet);
				//boxes.get(j).pName = analyzer.getProtocolName();
				
				if(analyzer.layer == 0)
				{
					//EthernetAnalyzer eth = new EthernetAnalyzer();
					//eth.analyze(packet);
					
					
					boxes.get(j).mName = analyzer.getValue("Destination MAC").toString();	
					boxes.get(j).direct = true;
					
					if(boxes.get(j).mName.equals(MovingBox.mach)){
						boxes.get(j).mName= analyzer.getValue("Source MAC").toString();
						boxes.get(j).direct = false;

						//System.out.println(boxes.get(j).toString());
						//System.out.println(boxes.get(j).index+"  "+boxes.get(j).mName+" "+boxes.get(j).direct);
					}
				}
				else if(analyzer.layer == 1 && (!boxes.get(j).pName.equals("ARP_RARP")))
				{	
					
					//IPv4Analyzer ip = new IPv4Analyzer();
					//ip.analyze(packet); 
					//error
					boxes.get(j).ipName= analyzer.getValue("Destination IP").toString();
					boxes.get(j).direct = true;
					
					if(boxes.get(j).ipName.equals(MovingBox.iph)){
						boxes.get(j).ipName= analyzer.getValue("Source IP").toString();
						boxes.get(j).direct = false;
					}
					//System.out.println(boxes.get(j).index+"  "+boxes.get(j).ipName+" "+boxes.get(j).direct);
					
				}
				
				else if(analyzer.layer == 1 && (boxes.get(j).pName.equals("ARP_RARP")))
				{
					ARPAnalyzer arp = new ARPAnalyzer();
					arp.analyze(packet);
					boxes.get(j).ipName= analyzer.getValue("Target Protocol Address").toString();
					boxes.get(j).direct = true;
					
					if(boxes.get(j).ipName.equals(MovingBox.iph)){
						boxes.get(j).ipName=  analyzer.getValue("Sender Protocol Address").toString();
						boxes.get(j).direct = false;
					}
					//System.out.println(boxes.get(j).index+"  "+boxes.get(j).ipName+" "+boxes.get(j).direct);
				}
				
			}
			}		
		}
		

	}
	void setBox(Packet packet){
		
		PacketBox pb = new PacketBox(boxSize, packet);
		
		for(JDPacketAnalyzer analyzer:analyzers){
			
			
			if(analyzer.isAnalyzable(packet)){
				
				{
					analyzer.analyze(packet);
					pb.pName = analyzer.getProtocolName();
			
				}
			}
		}
		boxes.add(pb);

	}
	
	public void clear(){
		jp.removeAll();
		boxes.clear();
		MovingBox.beforeCurrentItem = 0;
		MovingBox.currentItem = 0;
		MovingBox.wishItem = 0;
		init();
	}
	
	public void removeBox(int index){
		
		jp.remove(boxes.get(index));
		boxes.remove(index);
		
		adjustAllBoxesSize();
		adjustAllBoxesLocation();
	}
	public void stopRun()
	{
		this.stopPoint = true;	
		System.out.println("stopRun");
	}
	public void run() {
		
		if(!boxes.isEmpty()){
			System.out.println("boxes was not empty");
			boxes.clear();}
		
		while(lastPoint){
			
			try{
				//System.out.println(packets.get(boxSize).toString());
					
				setBox(packets.get(boxSize));
				setBoxBounds(boxes.get(boxSize));
					
				revalidate();
				repaint();
					
				boxSize++;
			
			}catch(Exception e){
				
				//System.out.println("nothing");
				
			}
			System.out.println(VncFrame.packSize + " "+boxSize);
			if(stopPoint && (VncFrame.packSize == boxSize)){
				lastPoint = false;
				this.t.interrupt();
			}
			
		}
	}
	
	
	@SuppressWarnings("deprecation")
	public void setBoxBounds(final PacketBox box) throws InterruptedException{
		//setBoxSize(box);
		//setBoxLocation(box);
		
		if(boxes.indexOf(box) == 0){
			box.setIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_0.png"), MovingBox.currentD.width, MovingBox.currentD.height));
			box.setRolloverIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_1.png"), MovingBox.currentD.width, MovingBox.currentD.height));
			box.setLabel("1");
			box.setFont(new Font("1", Font.PLAIN, 10));
			box.setVerticalTextPosition(SwingConstants.BOTTOM);
	        box.setHorizontalTextPosition(SwingConstants.CENTER);
			MovingBox.removeBoxBorder(box);
			box.setBounds(MovingBox.startP.x, MovingBox.currentP.y, MovingBox.currentD.width, MovingBox.currentD.height+14);
					
			
		}else{
			
			if(boxes.indexOf(box) == MovingBox.currentItem){

				box.setIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_0.png"), MovingBox.currentD.width, MovingBox.currentD.height));
				box.setRolloverIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_1.png"), MovingBox.currentD.width, MovingBox.currentD.height));
				box.setLabel(Integer.toString(boxes.indexOf(box)+1));
				box.setFont(new Font(Integer.toString(boxes.indexOf(box)+1), Font.PLAIN, 10));
				box.setVerticalTextPosition(SwingConstants.BOTTOM);
		        box.setHorizontalTextPosition(SwingConstants.CENTER);
				MovingBox.removeBoxBorder(box);
			
				box.setBounds(boxes.get(boxes.indexOf(box)-1).getLocation().x + boxes.get(boxes.indexOf(box)-1).getSize().width,
						MovingBox.currentP.y,
						MovingBox.currentD.width, MovingBox.currentD.height+14);

			}else{
				
				box.setIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_0.png"), MovingBox.restD.width, MovingBox.restD.height));
				box.setRolloverIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_1.png"), MovingBox.restD.width, MovingBox.restD.height));
				box.setLabel(Integer.toString(boxes.indexOf(box)+1));
				box.setFont(new Font(Integer.toString(boxes.indexOf(box)+1), Font.PLAIN, 10));
				box.setVerticalTextPosition(SwingConstants.BOTTOM);
		        box.setHorizontalTextPosition(SwingConstants.CENTER);
				MovingBox.removeBoxBorder(box);
				
				box.setBounds(boxes.get(boxes.indexOf(box)-1).getLocation().x + boxes.get(boxes.indexOf(box)-1).getSize().width,
						MovingBox.startP.y,
						MovingBox.restD.width, MovingBox.restD.height+14);
				
			}
			
		}
		
		
		box.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				
				MovingBox.wishItem = boxes.indexOf(box);
				
				// don't know why... but there is element sometimes in index -1
				if(MovingBox.wishItem == -1){
					System.out.println("this happen");
					boxes.add(0, box);
					MovingBox.wishItem = 0;				
				}
				
				if (e.getClickCount() == 1){
					//stage 3
					//System.out.println(boxes.indexOf(box) + " Single clicked!!");
					AddrTable.sBox = box;
					mb.at.mappingTable();
					if(box.direct)
					{
						AddrTable.jlLeft.setVisible(false);
						AddrTable.jlRight.setVisible(true);
						
						
					}
					else if(!box.direct){
						
						AddrTable.jlRight.setVisible(false);
						AddrTable.jlLeft.setVisible(true);
					}
					if(MovingBox.currentItem != MovingBox.wishItem){
						MovingBox.beforeCurrentItem = MovingBox.currentItem;
						MovingBox.currentItem = MovingBox.wishItem;
						
						//Remove PacketDetail LayeredPane
						mb.remove(mb.pd);
						//here need to add AddrTable
						mb.add(mb.at);
						mb.at.repaint();
						
						adjustAllBoxesSize();
						adjustAllBoxesLocation();
						mb.bc.revalidate();
						mb.bc.repaint();
						
						getHorizontalScrollBar().setValue(boxes.get(MovingBox.currentItem).getLocation().x - MovingBox.spaceD.width);

					}
				} else if (e.getClickCount() == 2){
					//System.out.println(boxes.indexOf(box) + " Double clicked!!");
					
					if(MovingBox.currentItem == MovingBox.wishItem){
						// go stage4				
						//System.out.println("We go stage 4!!");
						
						//here need to remove AddrTable
						
						//Add PacketDetail LayeredPane
						
						mb.remove(mb.at);
						mb.add(mb.pd);
						
						mb.pd.setPacket(boxes.get(MovingBox.currentItem).packet);
						mb.pd.init();
	                     
					}
				}
				
			}
		});
		
		/*
		box.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				
				MovingBox.wishItem = boxes.indexOf(box);
				
				System.out.println(boxes.indexOf(box));
				
				if(MovingBox.currentItem == MovingBox.wishItem){
					// go stage4
				}else{
					MovingBox.beforeCurrentItem = MovingBox.currentItem;
					MovingBox.currentItem = MovingBox.wishItem;
					adjustAllBoxesSize();
					adjustAllBoxesLocation();
				}
				
			}
		});
		*/
		
		adjustAllBoxesLocation();
		
		jp.add(box);
		
		jp.setPreferredSize(new Dimension(MovingBox.currentD.width + (boxes.size()-1)*MovingBox.restD.width + (MovingBox.spaceD.width*2), 600));
		
		/*//animation
		int i = 1;
		
		while(!box.getSize().equals(MovingBox.currentD)){
			
			box.setSize(box.getSize().width+1, box.getSize().height+1);
			box.setIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_0.png"), box.getSize().width+1, box.getSize().height+1));
			box.setRolloverIcon(scaleImageIcon(getImageIcon("/packet_images/"+ box.pName +"_1.png"), box.getSize().width+1, box.getSize().height+1));
			
			jp.setPreferredSize(new Dimension(boxes.size()*MovingBox.currentD.width, 600));
			
			revalidate();
			repaint();
			
			i++;
			//if(i>10) i = i/2;
			if(i<83) Thread.sleep(2);
			else Thread.sleep(30);
			
		}
		*/
		
		
	}

	
	public void adjustAllBoxesSize(){
		
		boxes.get(MovingBox.beforeCurrentItem).setIcon(scaleImageIcon(getImageIcon("/packet_images/"+ boxes.get(MovingBox.beforeCurrentItem).pName +"_0.png"), MovingBox.restD.width, MovingBox.restD.height));
		boxes.get(MovingBox.beforeCurrentItem).setRolloverIcon(scaleImageIcon(getImageIcon("/packet_images/"+ boxes.get(MovingBox.beforeCurrentItem).pName +"_1.png"), MovingBox.restD.width, MovingBox.restD.height));
		
		boxes.get(MovingBox.currentItem).setIcon(scaleImageIcon(getImageIcon("/packet_images/"+ boxes.get(MovingBox.currentItem).pName +"_0.png"), MovingBox.currentD.width, MovingBox.currentD.height));
		boxes.get(MovingBox.currentItem).setRolloverIcon(scaleImageIcon(getImageIcon("/packet_images/"+ boxes.get(MovingBox.currentItem).pName +"_1.png"), MovingBox.currentD.width, MovingBox.currentD.height));
	}
	
	public void adjustAllBoxesLocation(){
		
		for(int i=0; i < boxes.size(); i++){
			if(i == 0){
				
				if(i == MovingBox.currentItem)	
					boxes.get(i).setBounds(MovingBox.startP.x, MovingBox.currentP.y, MovingBox.currentD.width, MovingBox.currentD.height+14);
			
				else
					boxes.get(i).setBounds(MovingBox.startP.x, MovingBox.startP.y, MovingBox.restD.width, MovingBox.restD.height+14);
				

			}else{
				if(i == MovingBox.currentItem)	
					boxes.get(i).setBounds(boxes.get(i-1).getLocation().x + boxes.get(i-1).getSize().width,
							MovingBox.currentP.y,
							MovingBox.currentD.width, MovingBox.currentD.height+14);
			
				else
					boxes.get(i).setBounds(boxes.get(i-1).getLocation().x + boxes.get(i-1).getSize().width,
							MovingBox.startP.y,
							MovingBox.restD.width, MovingBox.restD.height+14);
				
			}
		}
		
		// this.getHorizontalScrollBar().setValue(boxes.get(MovingBox.currentItem).getLocation().x - MovingBox.spaceD.width);
		
	}
	
	
}
